//
//  XXCameraTool.m
//  CameraDemo
//
//  Created by sanfang on 2017/1/3.
//  Copyright © 2017年 ziz. All rights reserved.
//

#import "XXCameraTool.h"
#import <AssetsLibrary/AssetsLibrary.h>
@interface XXCameraTool ()


/**
 聚焦图片
 */
@property (nonatomic, weak) UIImageView *focusCursorImageView;

/**
 遮罩视图
 */
@property (nonatomic, strong)UIView* maskView;

/**
 该对象用来执行输入设备和输出设备间的数据传递
 */
@property (nonatomic, strong)AVCaptureSession* session;

/**
 输入设备
 */
@property (nonatomic, strong)AVCaptureDeviceInput* videoInput;

/**
 照片输出流
 */
@property (nonatomic, strong)AVCaptureStillImageOutput* photoOutput;

/**
 预览图层
 */
@property (nonatomic, strong)AVCaptureVideoPreviewLayer* previewLayer;



/**
 拍照按钮
 */
@property (nonatomic, strong)UIButton* shutterBtn;

@end

@implementation XXCameraTool



#pragma  mark === Public method ===
+(instancetype)shareInstance
{
    static XXCameraTool *sharedTool = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedTool = [[ XXCameraTool alloc]init];
    });
    return  sharedTool;
}

-(void)enterCameraInSuperView:(UIView *)superView
{
    if (self.session) {
        [self.session startRunning];
    }
//    [superView addSubview:self.focusCursorImageView];
    self.maskView = superView;
    [self setupCameraLayer];
}

-(void)takePhoto
{
    AVCaptureConnection *photoConnection = [self.photoOutput connectionWithMediaType:AVMediaTypeVideo];
    UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice]orientation];
    AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation];
    [photoConnection setVideoOrientation:avcaptureOrientation];
    [photoConnection setVideoScaleAndCropFactor:1];
    [self.photoOutput captureStillImageAsynchronouslyFromConnection:photoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate);
        ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
        if (author == ALAuthorizationStatusRestricted || author ==  ALAuthorizationStatusDenied)
        {
            //无权限
            return ;
        }
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
        [library writeImageDataToSavedPhotosAlbum:jpegData metadata:(__bridge id)attachments completionBlock:^(NSURL *assetURL, NSError *error) {
            
        }];
    }];
    
}

/**
 离开拍摄界面
 */
-(void)exitCamera
{
    if (self.session) {
        [self.session stopRunning];
    }
}

-(void)toggleCamera
{
    NSInteger cameraCount = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo].count;
    if (cameraCount > 1) {
        NSError *error;
        AVCaptureDeviceInput *newVideoInput;
        AVCaptureDevicePosition position = [self.videoInput device].position;
        if (position == AVCaptureDevicePositionBack) {
            newVideoInput = [[AVCaptureDeviceInput alloc]initWithDevice:[self frontCamera] error:&error];
        }
        else if (position == AVCaptureDevicePositionFront)
        {
            newVideoInput = [[AVCaptureDeviceInput alloc]initWithDevice:[self backCamera] error:&error];
        }
        else
        {
            return;
        }
        if (nil != newVideoInput)
        {
            [self.session beginConfiguration];
            [self.session removeInput:self.videoInput];
            if ([self.session canAddInput:newVideoInput]) {
                [self.session addInput:newVideoInput];
                [self setVideoInput:newVideoInput];
            }
            else
            {
                [self.session addInput:self.videoInput];
            }
            [self.session commitConfiguration];
        }
        else if (error)
        {
            NSLog(@"toggle camera fail error = %@", error);
        }
    }
}

/*
-(void)shutterCamera
{
    AVCaptureConnection *videoConnection = [self.photoOutput connectionWithMediaType:AVMediaTypeVideo];
    if (!videoConnection) {
        NSLog(@"take photo faild!");
        return;
    }
    [self.photoOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        if (imageDataSampleBuffer == NULL) {
            return ;
        }
        NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [UIImage imageWithData:imageData];
        NSLog(@"imgSize = %#", NSStringFromCGSize(image.size));
    }];
}
*/

-(void)setFlashMode:(AVCaptureFlashMode)mode
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [device lockForConfiguration:nil];
    if ([device hasFlash]) {
        [device setFlashMode:mode];
    }
    else{
        NSLog(@"设备不支持闪光灯");
    }
    [device unlockForConfiguration];
}

-(BOOL)getTorchState
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [device lockForConfiguration:nil];
    if ([device hasTorch]) {
        if (device.torchMode == AVCaptureTorchModeOn)
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    else
    {
        return NO;
    }
}


-(void)setTorchOn:(BOOL)toOn
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [device lockForConfiguration:nil];
    if ([device hasTorch]) {
        if (toOn) {
            [device setTorchMode:AVCaptureTorchModeOn];
            [device setFlashMode:AVCaptureFlashModeOn];
        }
        else
        {
            [device setTorchMode:AVCaptureTorchModeOff];
            [device setFlashMode:AVCaptureFlashModeOff];
        }
    }
    else
    {
        NSLog(@"设备不支持闪光灯");
    }
}

-(void)focusCursorInPoint:(CGPoint)point
{
    CGPoint cameraPoint = [self.previewLayer captureDevicePointOfInterestForPoint:point];
    [self setFocusCursorWithPoint:point];
    [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];
}

#pragma mark  === privavte method ===
- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initAVCaptureSession];
    }
    return self;
}

/**
 实例化session
 */
-(void)initAVCaptureSession
{
    self.session = [[AVCaptureSession alloc]init];
    
    NSError *error;

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    //设置闪光灯时必须先锁定设备，设置完毕后再解锁，否则崩溃
    [device lockForConfiguration:nil];
    [device setFlashMode:AVCaptureFlashModeAuto];
    [device unlockForConfiguration];
    
    self.videoInput = [[AVCaptureDeviceInput alloc]initWithDevice:device error:&error];
    if (error) {
        NSLog(@"error = %@", error);
    }
    
    self.photoOutput = [[AVCaptureStillImageOutput alloc]init];
    
    NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [self.photoOutput setOutputSettings:outputSettings];
    
    if ([self.session canAddInput:self.videoInput]) {
        [self.session addInput:self.videoInput];
    }
    if ([self.session canAddOutput:self.photoOutput]) {
        [self.session addOutput:self.photoOutput];
    }
}


/**
 *  设置聚焦光标位置
 *
 *  @param point 光标位置
 */
-(void)setFocusCursorWithPoint:(CGPoint)point{
    self.focusCursorImageView.center=point;
    self.focusCursorImageView.transform=CGAffineTransformMakeScale(1.5, 1.5);
    self.focusCursorImageView.alpha=1.0;
    [UIView animateWithDuration:1.0 animations:^{
        self.focusCursorImageView.transform=CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        self.focusCursorImageView.alpha=0;
        
    }];
}

/**
 *  设置聚焦
 */
-(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{
    
    AVCaptureDevice *captureDevice = self.videoInput.device;
    // 锁定配置
    [captureDevice lockForConfiguration:nil];
    
    // 设置聚焦
    if ([captureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
        [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];
    }
    if ([captureDevice isFocusPointOfInterestSupported]) {
        [captureDevice setFocusPointOfInterest:point];
    }
    
    // 设置曝光captureDevice
    if ([captureDevice isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {
        [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];
    }
    if ([captureDevice isExposurePointOfInterestSupported]) {
        [captureDevice setExposurePointOfInterest:point];
    }
    
    // 解锁配置
    [captureDevice unlockForConfiguration];
}

#pragma mark === lazyLoad ===

/**
 *  懒加载聚焦视图
 *
 */
- (UIImageView *)focusCursorImageView
{
    if (_focusCursorImageView == nil) {
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"touch_focus_x"]];
        _focusCursorImageView = imageView;
        [self.maskView addSubview:_focusCursorImageView];
    }
    return _focusCursorImageView;
}
/**
 懒加载预览视图
 */
-(AVCaptureVideoPreviewLayer *)previewLayer
{
    if (nil == _previewLayer) {
        //初始化预览图层
        _previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
        [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    }
    return _previewLayer;
}

/**
设置预览视图
 */
-(void)setupCameraLayer
{
    CALayer *maskLayer = self.maskView.layer;
    maskLayer.masksToBounds = YES;
    self.previewLayer.frame = self.maskView.bounds;
    CALayer *bottomLayer = maskLayer.sublayers[0];
    [maskLayer insertSublayer:self.previewLayer below:bottomLayer];
}

/**
 获取摄像头

 @param position 摄像头位置
 */
-(AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if ([device position] == position) {
            return device;
        }
    }
    return nil;
}

/**
 获取前置摄像头
 */
-(AVCaptureDevice *)frontCamera
{
    return [self cameraWithPosition:AVCaptureDevicePositionFront];
}

/**
 获取后置摄像头
 */
-(AVCaptureDevice *)backCamera
{
    return [self cameraWithPosition:AVCaptureDevicePositionBack];
}

#pragma mark  ===

//获取设备方向
-(AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation
{
    AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)deviceOrientation;
    if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
        result = AVCaptureVideoOrientationLandscapeRight;
    }
    else if (deviceOrientation == UIDeviceOrientationLandscapeRight)
    {
        result = AVCaptureVideoOrientationLandscapeLeft;
    }
    return result;
}

@end
